﻿'
' DotNetNuke® - http://www.dotnetnuke.com
' Copyright (c) 2002-2006
' by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
'
' Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
' documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
' the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
' to permit persons to whom the Software is furnished to do so, subject to the following conditions:
'
' The above copyright notice and this permission notice shall be included in all copies or substantial portions 
' of the Software.
'
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
' TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
' CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
' DEALINGS IN THE SOFTWARE.
'

Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.Common

Imports DotNetNuke.Entities.Modules
Imports DotNetNuke.Modules.Reports.Data
Imports DotNetNuke.Modules.Reports.Exceptions
Imports DotNetNuke.Modules.UserDefinedTable

Namespace DotNetNuke.Modules.Reports.DataSources.UDT

    ''' <summary>
    ''' A Data Source that provides data by querying a User Defined Table Module
    ''' </summary>
    Public Class UDTModuleDataSource
        Inherits DataSourceBase

        Public Overrides Function ExecuteReport(ByVal report As ReportInfo, _
                                      ByVal hostModule As Entities.Modules.PortalModuleBase, _
                                      ByVal inputParameters As IDictionary(Of String, Object)) As System.Data.DataView
            MyBase.ExecuteReport(report, hostModule, inputParameters)

            Dim moduleId As Integer = SettingsUtil.GetDictionarySetting(Of Integer)(report.DataSourceSettings, UDTDataSourceController.SETTING_UDT_ModuleID, -1)
            If moduleId = -1 Then
                ThrowMissingUDTModuleException()
            End If

            ' This is a quick and dirty, low performance, way to do this, so a perf optimization
            ' will be necessary.

            Dim filter As String = SettingsUtil.GetDictionarySetting(Of String)(report.DataSourceSettings, UDTDataSourceController.SETTING_UDT_Filter, String.Empty)
            Dim sort As String = SettingsUtil.GetDictionarySetting(Of String)(report.DataSourceSettings, UDTDataSourceController.SETTING_UDT_Sort, String.Empty)
            Dim cleanUp As Boolean = SettingsUtil.GetDictionarySetting(Of Boolean)(report.DataSourceSettings, UDTDataSourceController.SETTING_UDT_CleanUp, False)
            Dim colListStr As String = SettingsUtil.GetDictionarySetting(Of String)(report.DataSourceSettings, UDTDataSourceController.SETTING_UDT_ColumnList, "*")
            Dim colList As String() = colListStr.Split(",")

            Dim udtCtrl As UserDefinedTableController = New UserDefinedTableController()
            Dim udtDS As DataSet = udtCtrl.GetDataSet(moduleId)
            If udtDS Is Nothing Then
                ThrowMissingUDTModuleException()
            End If
            Dim udtDT As DataTable = udtDS.Tables(UserDefinedTable.DataSetTableName.Data)

            ' Select filter can applied over all rows, including invisible rows.
            If Trim(filter).Length > 0 Then
                For Each row As DataRow In udtDT.Select(String.Format("not({0})", filter))
                    udtDT.Rows.Remove(row)
                Next
            End If

            ' Filter the columns
            Dim toRemove As List(Of DataColumn) = New List(Of DataColumn)
            For Each dc As DataColumn In udtDT.Columns
                If Array.IndexOf(colList, dc.ColumnName) = -1 AndAlso Not colListStr.Equals("*", StringComparison.OrdinalIgnoreCase) Then
                    toRemove.Add(dc)
                End If
            Next

            ' Have to make a list first because if we remove while iterating it will break
            ' the enumerator, so now we run over this, separate, list and remove the columns
            For Each dc As DataColumn In toRemove
                udtDT.Columns.Remove(dc)
            Next

            'Clean up _UDT_*
            If cleanUp Then
                For Each dc As DataColumn In udtDT.Columns
                    If dc.ColumnName Like "*_UDT_*" Then
                        Dim newName As String = dc.ColumnName.Substring(0, dc.ColumnName.IndexOf("_UDT_"))
                        If Not udtDT.Columns.Contains(newName) Then
                            dc.ColumnName = newName
                        End If
                    End If
                Next
            End If

            ' Apply filters and sort to a new data view
            Dim dv As New DataView(udtDT)
            dv.Sort = sort
            Return dv
        End Function

        Private Sub ThrowMissingUDTModuleException()
            Throw New DataSourceException(New LocalizedText("NoSuchUDTModule.Text", Me.ExtensionContext.ResolveExtensionResourcesPath("DataProvider.ascx")), "There is no configured UDT Module or the configured module has been removed")
        End Sub
    End Class

End Namespace
